﻿using System.Collections.Generic;
using System.Configuration;
using log4net;
using Taype.Trading.BTC.TradeHillAPIClient.JSONObjects;
using Taype.Trading.BTC.Utilities;

namespace Taype.Trading.BTC.TradeHillAPIClient
{
    /// <summary>
    /// Encapsulates the functionality in v1 of the TradeHill API 
    /// </summary>
    public class v1
    {

        private static readonly ILog logger = LogManager.GetLogger(typeof(v1));

        /// <summary>
        /// Make sure to check app.config and make sure you are working in the correct environment (test or production)
        /// </summary>
        private string baseURL = ConfigurationManager.AppSettings["baseURL"] + "/APIv1/";
        
        private string name = ConfigurationManager.AppSettings["name"];

        private string pass = ConfigurationManager.AppSettings["pass"];

        /// <summary>
        /// Default constructor gets configuration from app.config
        /// </summary>
        public v1()
        { 
        
        }

        /// <summary>
        /// Orderbook: https://api.tradehill.com/APIv1/USD/Orderbook 
        /// </summary>
        /// <param name="currency"></param>
        /// <returns></returns>
        public List<TradeHillOrderBookEntry> OrderBook(TradeHillCurrencySymbol currency)
        {
            string url = baseURL + currency.ToString() + "OrderBook";
            string responseStr = (new TradeHillNetTools()).DoUnauthenticatedAPIPost(url, "");
            return TradeHillOrderBookEntry.getObjects(responseStr);
        }
   
        /// <summary>
        /// Trades: https://api.tradehill.com/APIv1/USD/Trades 
        /// </summary>
        /// <param name="currency"></param>
        /// <returns></returns>
        public List<TradeHillTrade> Trades(TradeHillCurrencySymbol currency)
        {
            string url = baseURL + currency.ToString() + "Trades";
            string responseStr = (new TradeHillNetTools()).DoUnauthenticatedAPIPost(url, "");
            return TradeHillTrade.getObjects(responseStr);
        }
    
        /// <summary>
        /// Ticker: https://api.tradehill.com/APIv1/USD/Ticker
        /// </summary>
        /// <param name="currency"></param>
        /// <returns></returns>
        public List<TradeHillTickerItem> Ticker(TradeHillCurrencySymbol currency)
        {
            string url = baseURL + currency.ToString() + "/Ticker";
            string responseStr = (new TradeHillNetTools()).DoUnauthenticatedAPIPost(url, "");
            return TradeHillTickerItem.getObjects(responseStr);
        }

        /// <summary>
        /// //Get Your Current Balance
        /// https://api.tradehill.com/APIv1/USD/GetBalance
        /// Returns your current balance for the specified currency and for BTC.
        /// Inputs:
        /// name: TradeHill Username
        /// pass: TradeHill Password
        /// Return: Dictionary of Currency, Amount pairs. Also returns XXX_Available which represents the balance which is actually available for trading. Also returns XXX_Reserved which represents the amount of funds which have been reserved due to open market orders or open withdrawal requests. 
        /// </summary>
        /// <param name="currency"></param>
        /// <param name="name"></param>
        /// <param name="pass"></param>
        /// <returns></returns>
        public List<TradeHillBalanceInfo> GetBalance(TradeHillCurrencySymbol currency, string name, string pass)
        {
            string url = baseURL + currency.ToString() + "GetBalance";
            string responseStr = (new TradeHillNetTools()).DoAuthenticatedAPIPost(url, name, pass, "");
            return TradeHillBalanceInfo.getObjects(responseStr);
        }

        /// <summary>
        /// Get Your Profile
        /// https://api.tradehill.com/APIv1/USD/GetProfile
        /// Returns your TradeHill Profile
        /// Inputs:
        /// name: TradeHill Username
        /// pass: TradeHill Password
        /// Return: Dictionary containing the following fields:
        /// Email: The email address associated with this account. This is the same as your TradeHill Username.
        /// BTC Deposit Address: Static BTC Deposit Address for this account.
        /// Referral Code: Referral code for this account.
        /// Commission Rate: Value representing the commission charged for trades made on this account. Value is a percentage. Ex: 0.60%
        /// </summary>
        /// <param name="currency"></param>
        /// <param name="name"></param>
        /// <param name="pass"></param>
        /// <returns></returns>
        public List<TradeHillProfileInfo> GetProfile(TradeHillCurrencySymbol currency, string name, string pass)
        {
            string url = baseURL + currency.ToString() + "GetProfile";
            string responseStr = (new TradeHillNetTools()).DoAuthenticatedAPIPost(url, name, pass, "");
            return TradeHillProfileInfo.getObjects(responseStr);
        }

        /// <summary>
        /// Get a List of Open Orders
        /// https://api.tradehill.com/APIv1/USD/GetOrders
        /// Returns your currently open orders in this currency.
        /// Inputs:
        /// name: TradeHill Username
        /// pass: TradeHill Password
        /// Return: Dictionary containing an 'orders' array. The orders array contains dictionaries with the following fields:
        /// type: 1 for Sell order; 2 for Buy order.
        /// status: Status of the order. All orders returned will have a status of 1 which means that they are active. Orders pending cancel are still considered active and will be returned in this list as active. Orders which were not accepted (invalid funds, etc) will not be returned in this list. Orders which have been successfully canceled will not be returned in this list.
        /// oid: The unique order id.
        /// symbol: The symbol of the item being bought or sold. Currently hardcoded to BTC.
        /// price: The limit price of your order. This will match the currency you are operating in. In this case, USD.
        /// amount_orig: The original amount (size) of your order.
        /// amount: The amount (size) of your order that remains to be filled. [amount = amount_orig - amount filled]
        /// reserved_amount: The amount of money reserved in order to fill this order. Includes estimated commissions.
        /// reserved_currency: The currency of the reserved money. In this case, either USD or BTC.
        /// date: The datetime this order was created.
        /// </summary>
        /// <param name="currency"></param>
        /// <param name="name"></param>
        /// <param name="pass"></param>
        /// <returns></returns>
        public List<TradeHillOrder> GetOrder(TradeHillCurrencySymbol currency, string name, string pass)
        {
            string url = baseURL + currency.ToString() + "GetOrders";
            string responseStr = (new TradeHillNetTools()).DoAuthenticatedAPIPost(url, name, pass, "");
            return TradeHillOrder.getObjects(responseStr);
        }

        /// <summary>
        /// Place a Limit Order to Buy BTC
        /// https://api.tradehill.com/APIv1/USD/BuyBTC
        /// Submit a limit order to buy BTC using this currency.
        /// Inputs:
        /// name: TradeHill Username
        /// pass: TradeHill Password
        /// price: Limit order price. The maximum price you are willing to pay for each BTC.
        /// amount: Amount of BTC you want to buy.
        /// Return: List of all open orders you have. Identical to what is returned by GetOrders.
        /// Note: You may only have up to 100 orders open at the same time. 
        /// </summary>
        /// <param name="currency"></param>
        /// <param name="name"></param>
        /// <param name="pass"></param>
        /// <param name="price"></param>
        /// <param name="amount"></param>
        /// <returns></returns>
        public List<TradeHillOrder> BuyBTC(TradeHillCurrencySymbol currency, string name, string pass, double price, double amount)
        {
            string url = baseURL + currency.ToString() + "BuyBTC";
            string moreArgs = "price=" + price.ToString() + "&amount=" + amount.ToString();
            string responseStr = (new TradeHillNetTools()).DoAuthenticatedAPIPost(url, name, pass, moreArgs);
            return TradeHillOrder.getObjects(responseStr);
        }

        /// <summary>
        /// Place a Limit Order to Sell BTC
        /// https://api.tradehill.com/APIv1/USD/SellBTC
        /// Submit a limit order to sell BTC using this currency.
        /// Inputs:
        /// name: TradeHill Username
        /// pass: TradeHill Password
        /// price: Limit order price. The minimum price you are willing to accept for each BTC.
        /// amount: Amount of BTC you want to sell.
        /// Return: List of all open orders you have. Identical to what is returned by GetOrders.
        /// Note: You may only have up to 100 orders open at the same time. 
        /// </summary>
        /// <param name="currency"></param>
        /// <param name="name"></param>
        /// <param name="pass"></param>
        /// <param name="price"></param>
        /// <param name="amount"></param>
        /// <returns></returns>
        public List<TradeHillOrder> SellBTC(TradeHillCurrencySymbol currency, string name, string pass, double price, double amount)
        {
            string url = baseURL + currency.ToString() + "SellBTC";
            string moreArgs = "price=" + price.ToString() + "&amount=" + amount.ToString();
            string responseStr = (new TradeHillNetTools()).DoAuthenticatedAPIPost(url, name, pass, moreArgs);
            return TradeHillOrder.getObjects(responseStr);
        }

        /// <summary>
        /// Cancel an Order
        /// https://api.tradehill.com/APIv1/USD/CancelOrder
        /// Submit a request to cancel an open order. This request will take time to process.
        /// Inputs:
        /// name: TradeHill Username
        /// pass: TradeHill Password
        /// oid: The order id of the order to be canceled.
        /// Return: List of all open orders you have. Identical to what is returned by GetOrders.
        /// Note: Canceling an order may take up to 1 second. During that time the order is considered active and will be returned as active by GetOrders. 
        /// </summary>
        /// <param name="currency"></param>
        /// <param name="name"></param>
        /// <param name="pass"></param>
        /// <param name="oid"></param>
        /// <returns></returns>
        public List<TradeHillOrder> CancelOrder(TradeHillCurrencySymbol currency, string name, string pass, string oid)
        {
            string url = baseURL + currency.ToString() + "CancelOrder";
            string moreArgs = "oid=" + oid;
            string responseStr = (new TradeHillNetTools()).DoAuthenticatedAPIPost(url, name, pass, moreArgs);
            return TradeHillOrder.getObjects(responseStr);
        }

        /// <summary>
        /// Get a List of all Open Withdrawal Requests & Those Completed in the Last 24 Hours
        /// https://api.tradehill.com/APIv1/USD/GetWithdrawals
        /// Returns your current open withdrawal requests as well as those recently completed in this currency.
        /// Inputs:
        /// name: TradeHill Username
        /// pass: TradeHill Password
        /// Return: Dictionary containing a 'withdrawals' array. The withdrawals array contains dictionaries with the following fields:
        /// id: The unique ID of this withdrawal request.
        /// status: Status of the request.
        /// startdate: The date this request was submitted.
        /// finishdate: The date this request was completed, failed, or canceled.
        /// amountrequested: The amount which was requested to be withdrawn.
        /// amountapproved: The amount which was approved to be withdrawn, and was subsequently debited from the account.
        /// method: The method of withdraw.
        /// currency: The currency of the withdrawn money.
        /// box_a: Additional details specified in Box A of the request.
        /// box_b: Additional details specified in Box B of the request.
        /// box_c: Additional details specified in Box C of the request.
        /// box_d: Additional details specified in Box D of the request.
        /// box_e: Additional details specified in Box E of the request.
        /// box_f: Additional details specified in Box F of the request.
        /// box_g: Additional details specified in Box G of the request.
        /// </summary>
        /// <param name="currency"></param>
        /// <param name="name"></param>
        /// <param name="pass"></param>
        /// <returns></returns>
        public List<TradeHillWithdrawal> GetWithdrawals(TradeHillCurrencySymbol currency, string name, string pass)
        {
            string url = baseURL + currency.ToString() + "GetWithdrawals";
            string responseStr = (new TradeHillNetTools()).DoAuthenticatedAPIPost(url, name, pass, "");
            return TradeHillWithdrawal.getObjects(responseStr);
        }

        /// <summary>
        /// Get a List of all Open Deposit Requests & Those Completed in the Last 24 Hours
        /// https://api.tradehill.com/APIv1/USD/GetDeposits
        /// Returns your current open deposit requests as well as those recently completed in this currency.
        /// Inputs:
        /// name: TradeHill Username
        /// pass: TradeHill Password
        /// Return: Dictionary containing a 'deposits' array. The deposits array contains dictionaries with the following fields:
        /// id: The unique ID of this deposit request.
        /// status: Status of the request.
        /// startdate: The date this request was submitted.
        /// finishdate: The date this request was completed, failed, or canceled.
        /// amountrequested: The amount which was requested to be deposited.
        /// amountapproved: The amount which was approved to be deposited, and was subsequently credited to the account.
        /// method: The method of deposit.
        /// currency: The currency of the deposited money.
        /// box_a: Additional details specified in Box A of the request.
        /// box_b: Additional details specified in Box B of the request.
        /// box_c: Additional details specified in Box C of the request.
        /// box_d: Additional details specified in Box D of the request.
        /// box_e: Additional details specified in Box E of the request.
        /// box_f: Additional details specified in Box F of the request.
        /// box_g: Additional details specified in Box G of the request.
        /// </summary>
        /// <param name="currency"></param>
        /// <param name="name"></param>
        /// <param name="pass"></param>
        /// <returns></returns>
        public List<TradeHillDeposit> GetDeposits(TradeHillCurrencySymbol currency, string name, string pass)
        {
            string url = baseURL + currency.ToString() + "GetDeposits";
            string responseStr = (new TradeHillNetTools()).DoAuthenticatedAPIPost(url, name, pass, "");
            return TradeHillDeposit.getObjects(responseStr);
        }

        /// <summary>
        /// Submit a request to withdraw funds
        /// https://api.tradehill.com/APIv1/USD/SubmitWithdrawalRequest
        /// Submit a request to withdraw funds in the specified currency.
        /// Inputs:
        /// name: TradeHill Username
        /// pass: TradeHill Password
        /// method: The method of withdrawal. Refer to the Method column here.
        /// amount: The amount to withdraw.
        /// box_a: Additional transaction details possibly required for this request.
        /// box_b: Additional transaction details possibly required for this request.
        /// box_c: Additional transaction details possibly required for this request.
        /// box_d: Additional transaction details possibly required for this request.
        /// box_e: Additional transaction details possibly required for this request.
        /// box_f: Additional transaction details possibly required for this request.
        /// box_g: Additional transaction details possibly required for this request.
        /// Return: List of all open withdrawal requests that you have. Identical to what is returned by GetWithdrawals.
        /// Note: You may only have up to 2 open withdrawal requests of the same type.
        /// Note: The requirements for data in box_a through box_g can be found on the instructions page of each withdrawal method. 
        /// </summary>
        /// <param name="currency"></param>
        /// <param name="name"></param>
        /// <param name="pass"></param>
        /// <param name="method"></param>
        /// <param name="amount"></param>
        /// <param name="box_a"></param>
        /// <param name="box_a"></param>
        /// <param name="box_b"></param>
        /// <param name="box_c"></param>
        /// <param name="box_d"></param>
        /// <param name="box_e"></param>
        /// <param name="box_f"></param>
        /// <param name="box_g"></param>
        /// <returns></returns>
        public List<TradeHillWithdrawal> SubmitWithdrawalRequest(TradeHillCurrencySymbol currency, string name, string pass, TradeHillWithdrawalType method, double amount, string box_a, string box_b, string box_c, string box_d, string box_e, string box_f, string box_g)
        {
            string url = baseURL + currency.ToString() + "SubmitWithdrawalRequest";
            string moreArgs = "method=" + method.ToString() + "&amount=" + amount.ToString() + "&box_a=" + box_a + "&box_b=" + box_b + "&box_c=" + box_c + "&box_d=" + box_d + "&box_e=" + box_e + "&box_f=" + box_f + "&box_g=" + box_g;
            string responseStr = (new TradeHillNetTools()).DoAuthenticatedAPIPost(url, name, pass, moreArgs);
            return TradeHillWithdrawal.getObjects(responseStr);
        }

        /// <summary>
        /// Submit a request to deposit funds
        /// https://api.tradehill.com/APIv1/USD/SubmitDepositRequest
        /// Submit a request to deposit funds in the specified currency.
        /// Inputs:
        /// name: TradeHill Username
        /// pass: TradeHill Password
        /// method: The method of deposit. Refer to the Method column here.
        /// amount: The amount to deposit.
        /// box_a: Additional transaction details possibly required for this request.
        /// box_b: Additional transaction details possibly required for this request.
        /// box_c: Additional transaction details possibly required for this request.
        /// box_d: Additional transaction details possibly required for this request.
        /// box_e: Additional transaction details possibly required for this request.
        /// box_f: Additional transaction details possibly required for this request.
        /// box_g: Additional transaction details possibly required for this request.
        /// Return: List of all open deposit requests that you have. Identical to what is returned by GetDeposits.
        /// Note: You may only have up to 2 open deposit requests of the same type.
        /// Note: The requirements for data in box_a through box_g can be found on the instructions page of each deposit method. 
        /// </summary>
        /// <param name="name"></param>
        /// <param name="pass"></param>
        /// <param name="method"></param>
        /// <param name="amount"></param>
        /// <param name="box_a"></param>
        /// <param name="box_a"></param>
        /// <param name="box_b"></param>
        /// <param name="box_c"></param>
        /// <param name="box_d"></param>
        /// <param name="box_e"></param>
        /// <param name="box_f"></param>
        /// <param name="box_g"></param>
        /// <returns></returns>
        public List<TradeHillDeposit> SubmitDepositRequest(TradeHillCurrencySymbol currency, string name, string pass, TradeHillDepositType method, double amount, string box_a, string box_b, string box_c, string box_d, string box_e, string box_f, string box_g)
        {
            string url = baseURL + currency.ToString() + "SubmitDepositRequest";
            string moreArgs = "method=" + method.ToString() + "&amount=" + amount.ToString() + "&box_a=" + box_a + "&box_b=" + box_b + "&box_c=" + box_c + "&box_d=" + box_d + "&box_e=" + box_e + "&box_f=" + box_f + "&box_g=" + box_g;
            string responseStr = (new TradeHillNetTools()).DoAuthenticatedAPIPost(url, name, pass, moreArgs);
            return TradeHillDeposit.getObjects(responseStr);
        }
    }
}
